# -*- coding: UTF-8 -*-
'''
TestRendererWithPi3d_004_WithWaveShaperMoreAction.py
Created on 05.02.2013

@author: p.hess
'''
import sys

from LinearSpreadGen import LinearSpread 
from LinearSpreadGen import SpreadType
from Transform import Transform
from Quad import Quad
from Animation import LFO
from Value import WaveShaper

from pi3d import Display
from pi3d.Camera import Camera
from pi3d.Keyboard import Keyboard
from pi3d.util.Screenshot import screenshot

from time import time


class test():
    
    def __init__(self):
        self.KeyboardQueue = None
        
    def setup(self):
        
        #
        # Setup Pi3D
        #
        
        self.DISPLAY = Display.create(0, 0) 
        # now we need a background color. We select black and a 
        # non opaque 
        self.DISPLAY.set_background(0, 0, 0, 1)  # r,g,b,alpha -> black background
        
        #
        # DISPLAY.frames_per_second
        #
        self.DISPLAY.frames_per_second = 25
        
        #
        # Setup keyboard handling
        #

        self.mykeys = Keyboard()        

        print "keyboard handling established" + '\n\r'


    def teardown(self):
        
        #
        # ensure, that all output is written to the display
        #
        sys.stdout.flush()
        
        #
        # down Pi3d
        #    
        self.DISPLAY.destroy()
        print "teardown Pi3d done"  + '\n\r'           
  
  
    def loop(self):    

        print "enter main loop"

        self.prepareSpreadableObjects()
        
        # do the first inisitalisation        
        
        self.keyboardControlledSpreadcount = 5
        self.keyboardControlledRotation = 0.0
        
        lasttime = time()
        loopCounter = 0
        
        while self.DISPLAY.loop_running():
            loopCounter += 1            
            
            self.computeFrame();
            
            # read keyboard not every loop. Slows down the loop            

            if (loopCounter % 1 == 0) :
                                
                k = self.mykeys.read()
                if k > -1:
                    if k == 112: screenshot("earthPic.jpg")    
                    elif k == 27: break # do end processing, finito, go to weekend
                    elif k==119:  # key w
                        self.keyboardControlledRotation -= 0.1
                        if (self.keyboardControlledRotation < 0): self.keyboardControlledRotation = 1
                    elif k==115: # key s
                        self.keyboardControlledRotation += 0.1
                        if (self.keyboardControlledRotation > 1): self.keyboardControlledRotation = 0
                    elif k == 97:  # key a
                        self.keyboardControlledSpreadcount -= 1 
                        if (self.keyboardControlledSpreadcount < 1): self.keyboardControlledSpreadcount = 1
                    elif k == 100: self.keyboardControlledSpreadcount += 1  # keay d
                    else: 
                        print "not processed key:" + str(k) + '\n\r'
    
                if (loopCounter % 100 == 0) :
                    currtime = time()
                    loopsPerSecond = 100.0 / (currtime - lasttime)
                    sys.stdout.write(str(time()) + "-" + str(loopCounter) + "-lps: " + str(loopsPerSecond) + '\n\r')
                    lasttime = currtime

            Camera.instance().was_moved = False
            
        print "exit main loop"  + '\n\r'


    def prepareSpreadableObjects(self):
        '''Creates all the objects which are used in the computeFrame method'''
        
        # Low Frequency Oscilators. They create a ramp up from 0..1 within the defined period
        # not spreadable in this version
        self.LFO         = LFO(Period_in=1.0)
        self.LFO4pulsing = LFO(Period_in=1.0)
        self.LFO4BigTurn = LFO(Period_in=6.0)
        
        # This spread is used for the line of the quads
        self.LinearSpreadLine = LinearSpread(SpreadCount_in=[5], 
                                             Input_in = [-.23,0,.3],    # <- new! Now spreads can used on the most inputs 
                                             Width_in=[1], 
                                             SpreadType_in=[SpreadType.Centered])
        
        # This spread is used to create differend sized Quads
        self.LinearSpreadScale = LinearSpread(Width_in=[.2], 
                                              SpreadCount_in=[1], 
                                              SpreadType_in=[SpreadType.Centered])
        
        # Handles the big rotation
        self.TransformRotation = Transform()
        
        # Helpds to make a sine wave from the LFO ramp
        self.WaveShaper = WaveShaper();
        
        # The inner transformation used for the Quad line and the inner rotation of the quads
        self.Transform = Transform(Transform_in=None,  
                                   TranslateX_in=None, 
                                   TranslateY_in=[0], 
                                   ScaleX_in=[0.1], 
                                   ScaleY_in=[0.1])
        
        # he builder of the Quads (planes)
        self.Quad = Quad()


    def computeFrame(self):
        '''compute the next frame to show'''

        # get the next LFO values for this frame        
        self.LFO4pulsing.update()
        self.LFO.update()
        self.LFO4BigTurn.update()
        
        # update the preads for Quads control, The number of Quads can be set via keyboard, 
        # and the size is morphed by a phase change
        self.LinearSpreadLine.update(SpreadCount_in=[self.keyboardControlledSpreadcount] , 
                                     Phase_in=self.LFO4pulsing.Output)
        # Update the spread which controls the size of the quads
        self.LinearSpreadScale.update(Phase_in=self.LFO4BigTurn.Output)
        
        # creates from the LFO ramp a sin value (this is the swinger...)
        self.WaveShaper.update(Input_in = self.LFO4BigTurn.Output)
        
        # Setup the overal rotation transformation
        self.TransformRotation.update(Rotate_in=self.WaveShaper.Output)
        
        # Setup the Quad transformation by the LFO's
        #print "self.LinearSpreadLine.Output:", self.LinearSpreadLine.Output, "\r"
        self.Transform.update(Transform_in=self.TransformRotation.transform_out,
                              TranslateX_in=self.LinearSpreadLine.Output,
                              TranslateY_in=self.LinearSpreadLine.Output,
                              ScaleX_in=self.LinearSpreadScale.Output,
                              ScaleY_in=self.LinearSpreadScale.Output,
                              Rotate_in=self.LFO.Output)
        #print "self.Transform.transform_out.maxcount:", self.Transform.transform_out.maxcount, "\r"
        #print "self.Transform.transform_out.translateX", self.Transform.transform_out.translateX, "\r"
        
        # paint the whole stuff.
        self.Quad.update(Transform=self.Transform.transform_out)

# end class --------------------------------------------------------------------------------------------
    
mytest = test()
mytest.setup()
mytest.loop()
mytest.teardown()
